package com.burst.reptile.framework.config;

import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;

import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.burst.reptile.framework.interceptor.RepeatSubmitInterceptor;

import lombok.RequiredArgsConstructor;

/**
 * 通用配置
 * 
 * @author wujin
 * @date: 2020年5月22日 下午5:13:29
 */
@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ResourcesConfig extends WebMvcConfigurationSupport {
	
	private final RepeatSubmitInterceptor repeatSubmitInterceptor;
	
	@Value("${spring.thymeleaf.cache}")
	private boolean thymeleafCacheEnable;
	
	/**
     * 静态资源加载配置
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    }

    /**
     * 跨域配置
     */
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**").allowedOrigins("*").allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
				.maxAge(3600).allowCredentials(true);
	}
	
	/**
     * 模板资源解析器
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.thymeleaf")
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.getApplicationContext());
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setCacheable(thymeleafCacheEnable);
        return templateResolver;
    }
    
    /**
     * 允许多请求地址多加斜杠  比如 /msg/list   //msg/list
     * @return
     */
    @Bean
    public HttpFirewall httpFirewall() {
        return new DefaultHttpFirewall();
    }
    
    /**
     * Thymeleaf标准方言解释器
     */
    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        // 支持Spring EL表达式
        templateEngine.setEnableSpringELCompiler(true);

        // 支持SpringSecurity方言
        SpringSecurityDialect securityDialect = new SpringSecurityDialect();
        templateEngine.addDialect(securityDialect);
        templateEngine.addDialect(new Java8TimeDialect());
        return templateEngine;
    }
    
    /**
     * 视图解析器
     */
    @Bean
    public ThymeleafViewResolver viewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        return viewResolver;
    }

    /**
     * 配置fastjson 
     */
	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		super.configureMessageConverters(converters);
		// 1.需要先定义一个convert 转换消息的对象；
		FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
		fastConverter.setFastJsonConfig(fastjsonConfig());
		fastConverter.setSupportedMediaTypes(getSupportedMediaType());
		ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
		// 4.将convert添加到converters当中
		converters.add(fastConverter);
	}

	/**
	 * 自定义拦截规则
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
	}

	/**
	 * fastjson的配置
	 */
	public FastJsonConfig fastjsonConfig() {
		FastJsonConfig fastJsonConfig = new FastJsonConfig();
		fastJsonConfig.setSerializerFeatures(
				//SerializerFeature.PrettyFormat, // 美化json输出，否则会作为整行输出
				SerializerFeature.WriteNullBooleanAsFalse, // Boolean类型字段为null时输出false而null
				SerializerFeature.WriteMapNullValue, // 字段为空是否输出给前端，需要则放开注释
				SerializerFeature.DisableCircularReferenceDetect, // 禁用循环引用检测
				SerializerFeature.BrowserCompatible,
				SerializerFeature.WriteEnumUsingToString);
//        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); //时间格式化类型  不设置默认为时间戳
		fastJsonConfig.setCharset(Charset.forName("utf-8"));
//        initOtherValueFilters(fastJsonConfig);

		// 解决Long转json精度丢失的问题
		SerializeConfig serializeConfig = SerializeConfig.globalInstance;
		serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
		serializeConfig.put(Long.class, ToStringSerializer.instance);
		serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
		fastJsonConfig.setSerializeConfig(serializeConfig);
		return fastJsonConfig;
	}

	/**
	 * 支持的mediaType类型
	 */
	public List<MediaType> getSupportedMediaType() {
		ArrayList<MediaType> mediaTypes = new ArrayList<>();
		mediaTypes.add(MediaType.APPLICATION_JSON);
		// 增加解析spring boot actuator结果的解析
		mediaTypes.add(MediaType.valueOf("application/vnd.spring-boot.actuator.v2+json"));
		return mediaTypes;
	}

	/**
	 * 初始化value过滤器 默认的valueFilter是把空的字段转化为空串
	 */
	protected void initOtherValueFilters(FastJsonConfig fastJsonConfig) {
		// 为空的值转化为空串
		ValueFilter nullValueFilter = (object, name, value) -> {
			if (null == value) {
				return "";
			} else {
				return value;
			}
		};
		fastJsonConfig.setSerializeFilters(nullValueFilter);
	}
	
	/**
	 * 配置解析器 配置这个会导致MultipartFile为空
	 * @return
	 */
//	@Bean(name = "multipartResolver")
//    public MultipartResolver multipartResolver() {
//        return new CustomMultipartResolver();
//    }

}